package de.unidue.langtech.teaching.pp.example;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.fit.component.JCasAnnotator_ImplBase;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;

import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
import de.unidue.langtech.teaching.pp.type.DetectedSentimentScore;


/**baseline sets detected sentiment regarding all words from tweet
 * @author Melissa
 *
 */
public class BaselineExample
    extends JCasAnnotator_ImplBase
{	
	
	// class field for storing wordlists.	
	private final List<String> negativeWords;
	private final List<String> positiveWords;

	// constructor
	public BaselineExample() throws IOException{
		super();
		
		// initialize class-wide word-lists.
		negativeWords = ReadWordList(new File("./src/main/java/de/unidue/langtech/teaching/pp/example/wordlists/negative-words.txt"));
		positiveWords = ReadWordList(new File("./src/main/java/de/unidue/langtech/teaching/pp/example/wordlists/positive-words.txt"));
		
	}
	
	
	
	
	/**
	 * @param file given wordlist-file
	 * @return wordlist
	 * @throws IOException if file not okay
	 * 
	 * Helper method to read a wordlist from uic.edu (semicolon is comment)
	 */
	public static List<String> ReadWordList(File file) throws IOException{

			// read all lines in file to list.
			List<String> lines =  FileUtils.readLines(file);
			// new list for storing valid words
			ArrayList<String> list = new ArrayList<String>();
			
			// foreach line (each word) in word-list
			for(String s : lines)
				// if line does not start with ;
				if(!s.startsWith(";"))
					// add to valid-word-list lowercased.
					list.add(s.trim().toLowerCase());

			return list;
	}
	
	
	/**
	 * @param t Token to check
	 * @return sentiment-score for given token
	 * 
	 * Method to get sentiment-score for a given text-token.
	 */
	private Integer checkToken(Token t){
		// get token-text (lowercased)
		String text = t.getCoveredText().toLowerCase();
		
		// set itial score to neutral
		Integer sentimentValue = 0;
		
		// if is hashtag? neutral!
		if(text.startsWith("#"))
			sentimentValue = 0;
		
		// if is a negative word, negative
		else if(negativeWords.contains(text))
			sentimentValue = -1;
		// if is positive word, positive
		else if(positiveWords.contains(text))
			sentimentValue = 1;
		
		// if is self-negating, invert score (e.g. "non-blocking")		
		if(text.startsWith("non"))
			sentimentValue = -sentimentValue;
				
		return sentimentValue;
	}
	
	/**Source: http://bytes.com/topic/java/answers/899855-negation-detection-text
	 * @param t Text Token
	 * @return boolean if Token is a negation-token
	 */
	private boolean checkTokenIsNegation(Token t){
		// get text of token
		String text = t.getCoveredText().toLowerCase();
		
		// if "not" or starts with "non" (e.g. "non", "non " or "non-")
		return text.equalsIgnoreCase("not") || text.startsWith("non"); 
	}
	
    @Override
    public void process(JCas jcas)
        throws AnalysisEngineProcessException
    {
    	System.out.println("TestdatenB.txt: " + jcas.getDocumentText());
        
        Collection<Token> tokens = JCasUtil.select(jcas, Token.class);
        System.out.println("CAS contains " + tokens.size() + " tokens.");
    	
        
        // initial document sentiment-score
        Integer sentiment = 0;
        
		// analyze
        // last token is negation?
        boolean negation = false;
        
        // for each token in document-tokens
        for(Token t : tokens){
        	 // check if current token is negation
        	if(checkTokenIsNegation(t)){
        		negation = true;
        		// if negation, set helper-variable and skip analytics
        		continue;
        	}
        	
        	// if last token was negation, substract score
        	if(negation)
        		sentiment -= checkToken(t);
        	// else add score
        	else
        		sentiment += checkToken(t);
        	
        	// reset negation status
        	negation = false;
        }        
        
        // annotate document with real sentiment-score
        DetectedSentimentScore score = new DetectedSentimentScore(jcas);
        score.setScore(sentiment);
        score.addToIndexes();
    }
}